import Foundation
import AVFoundation
import UIKit
import Combine

class CameraManager: NSObject, ObservableObject {
    @Published var isAuthorized = false
    @Published var isCameraUnavailable = false
    @Published var isFlashAvailable = false
    @Published var isFlashEnabled = false
    @Published var currentZoomFactor: CGFloat = 1.0
    
    private let captureSession = AVCaptureSession()
    private var photoOutput: AVCapturePhotoOutput?
    private var videoDeviceInput: AVCaptureDeviceInput?
    private var previewLayer: AVCaptureVideoPreviewLayer?
    
    private var captureCompletion: ((UIImage?) -> Void)?
    private let sessionQueue = DispatchQueue(label: "camera.session.queue")
    
    // Camera position tracking
    @Published var currentCameraPosition: AVCaptureDevice.Position = .back
    
    override init() {
        super.init()
        setupCaptureSession()
        checkCameraAuthorization()
    }
    
    // MARK: - Authorization
    
    func requestPermission() {
        sessionQueue.async {
            switch AVCaptureDevice.authorizationStatus(for: .video) {
            case .authorized:
                DispatchQueue.main.async {
                    self.isAuthorized = true
                }
                self.startSession()
                
            case .notDetermined:
                AVCaptureDevice.requestAccess(for: .video) { granted in
                    DispatchQueue.main.async {
                        self.isAuthorized = granted
                    }
                    if granted {
                        self.startSession()
                    }
                }
                
            case .denied, .restricted:
                DispatchQueue.main.async {
                    self.isAuthorized = false
                    self.isCameraUnavailable = true
                }
                
            @unknown default:
                DispatchQueue.main.async {
                    self.isAuthorized = false
                }
            }
        }
    }
    
    private func checkCameraAuthorization() {
        switch AVCaptureDevice.authorizationStatus(for: .video) {
        case .authorized:
            isAuthorized = true
        case .denied, .restricted:
            isCameraUnavailable = true
        default:
            break
        }
    }
    
    // MARK: - Session Setup
    
    private func setupCaptureSession() {
        sessionQueue.async {
            self.captureSession.beginConfiguration()
            
            // Set session preset
            if self.captureSession.canSetSessionPreset(.photo) {
                self.captureSession.sessionPreset = .photo
            }
            
            // Add video input
            self.setupVideoInput()
            
            // Add photo output
            self.setupPhotoOutput()
            
            self.captureSession.commitConfiguration()
        }
    }
    
    private func setupVideoInput() {
        do {
            guard let camera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else {
                DispatchQueue.main.async {
                    self.isCameraUnavailable = true
                }
                return
            }
            
            let videoDeviceInput = try AVCaptureDeviceInput(device: camera)
            
            if captureSession.canAddInput(videoDeviceInput) {
                captureSession.addInput(videoDeviceInput)
                self.videoDeviceInput = videoDeviceInput
                
                DispatchQueue.main.async {
                    self.isFlashAvailable = camera.hasFlash
                    self.currentCameraPosition = camera.position
                }
            }
            
        } catch {
            print("Error setting up video input: \(error)")
            DispatchQueue.main.async {
                self.isCameraUnavailable = true
            }
        }
    }
    
    private func setupPhotoOutput() {
        let photoOutput = AVCapturePhotoOutput()
        
        if captureSession.canAddOutput(photoOutput) {
            captureSession.addOutput(photoOutput)
            
            photoOutput.isHighResolutionCaptureEnabled = true
            photoOutput.maxPhotoQualityPrioritization = .quality
            
            self.photoOutput = photoOutput
        }
    }
    
    func setupPreview(in view: UIView) {
        sessionQueue.async {
            let previewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
            previewLayer.videoGravity = .resizeAspectFill
            previewLayer.connection?.videoOrientation = .portrait
            
            DispatchQueue.main.async {
                previewLayer.frame = view.bounds
                view.layer.sublayers?.removeAll()
                view.layer.addSublayer(previewLayer)
                self.previewLayer = previewLayer
            }
        }
    }
    
    // MARK: - Session Control
    
    func startSession() {
        sessionQueue.async {
            if !self.captureSession.isRunning {
                self.captureSession.startRunning()
            }
        }
    }
    
    func stopSession() {
        sessionQueue.async {
            if self.captureSession.isRunning {
                self.captureSession.stopRunning()
            }
        }
    }
    
    // MARK: - Photo Capture
    
    func capturePhoto(completion: @escaping (UIImage?) -> Void) {
        sessionQueue.async {
            guard let photoOutput = self.photoOutput else {
                DispatchQueue.main.async {
                    completion(nil)
                }
                return
            }
            
            self.captureCompletion = completion
            
            let photoSettings = AVCapturePhotoSettings()
            
            // Configure flash
            if self.isFlashAvailable {
                photoSettings.flashMode = self.isFlashEnabled ? .on : .off
            }
            
            // High quality settings
            if photoOutput.availablePhotoCodecTypes.contains(.hevc) {
                photoSettings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.hevc])
            }
            
            photoSettings.isHighResolutionPhotoEnabled = true
            photoSettings.photoQualityPrioritization = .quality
            
            photoOutput.capturePhoto(with: photoSettings, delegate: self)
        }
    }
    
    // MARK: - Camera Controls
    
    func switchCamera() {
        sessionQueue.async {
            guard let currentInput = self.videoDeviceInput else { return }
            
            self.captureSession.beginConfiguration()
            self.captureSession.removeInput(currentInput)
            
            let newPosition: AVCaptureDevice.Position = (self.currentCameraPosition == .back) ? .front : .back
            
            guard let newCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: newPosition) else {
                // Re-add the current input if new camera is unavailable
                self.captureSession.addInput(currentInput)
                self.captureSession.commitConfiguration()
                return
            }
            
            do {
                let newInput = try AVCaptureDeviceInput(device: newCamera)
                
                if self.captureSession.canAddInput(newInput) {
                    self.captureSession.addInput(newInput)
                    self.videoDeviceInput = newInput
                    
                    DispatchQueue.main.async {
                        self.currentCameraPosition = newPosition
                        self.isFlashAvailable = newCamera.hasFlash
                        self.currentZoomFactor = newCamera.videoZoomFactor
                    }
                }
            } catch {
                print("Error switching camera: \(error)")
                // Re-add the current input
                self.captureSession.addInput(currentInput)
            }
            
            self.captureSession.commitConfiguration()
        }
    }
    
    func toggleFlash() {
        isFlashEnabled.toggle()
    }
    
    func setZoom(_ factor: CGFloat) {
        sessionQueue.async {
            guard let device = self.videoDeviceInput?.device else { return }
            
            do {
                try device.lockForConfiguration()
                
                let maxZoom = min(factor, device.activeFormat.videoMaxZoomFactor)
                let minZoom = max(maxZoom, device.minAvailableVideoZoomFactor)
                
                device.videoZoomFactor = minZoom
                
                DispatchQueue.main.async {
                    self.currentZoomFactor = device.videoZoomFactor
                }
                
                device.unlockForConfiguration()
            } catch {
                print("Error setting zoom: \(error)")
            }
        }
    }
    
    func focusAt(point: CGPoint) {
        sessionQueue.async {
            guard let device = self.videoDeviceInput?.device else { return }
            
            do {
                try device.lockForConfiguration()
                
                if device.isFocusPointOfInterestSupported {
                    device.focusPointOfInterest = point
                    device.focusMode = .autoFocus
                }
                
                if device.isExposurePointOfInterestSupported {
                    device.exposurePointOfInterest = point
                    device.exposureMode = .autoExpose
                }
                
                device.unlockForConfiguration()
            } catch {
                print("Error setting focus: \(error)")
            }
        }
    }
}

// MARK: - AVCapturePhotoCaptureDelegate

extension CameraManager: AVCapturePhotoCaptureDelegate {
    func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        if let error = error {
            print("Photo capture error: \(error)")
            DispatchQueue.main.async {
                self.captureCompletion?(nil)
                self.captureCompletion = nil
            }
            return
        }
        
        guard let imageData = photo.fileDataRepresentation(),
              let image = UIImage(data: imageData) else {
            DispatchQueue.main.async {
                self.captureCompletion?(nil)
                self.captureCompletion = nil
            }
            return
        }
        
        // Process image orientation
        let processedImage = image.fixedOrientation()
        
        DispatchQueue.main.async {
            self.captureCompletion?(processedImage)
            self.captureCompletion = nil
        }
    }
}

// MARK: - UIImage Extension

extension UIImage {
    func fixedOrientation() -> UIImage {
        guard imageOrientation != .up else { return self }
        
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        draw(in: CGRect(origin: .zero, size: size))
        let normalizedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return normalizedImage ?? self
    }
}

// MARK: - Camera Preview

struct CameraPreview: UIViewRepresentable {
    let cameraManager: CameraManager
    
    func makeUIView(context: Context) -> UIView {
        let view = UIView(frame: UIScreen.main.bounds)
        cameraManager.setupPreview(in: view)
        return view
    }
    
    func updateUIView(_ uiView: UIView, context: Context) {
        // Update preview layer frame if needed
        if let previewLayer = uiView.layer.sublayers?.first as? AVCaptureVideoPreviewLayer {
            previewLayer.frame = uiView.bounds
        }
    }
}